
#include <linux/module.h>  
#include <linux/kernel.h>  
#include <linux/fs.h>  
#include <linux/init.h>  
#include <linux/delay.h>  
#include <linux/device.h>  
#include <linux/cdev.h>  
#include <linux/interrupt.h>  
#include <linux/sched.h>  
#include <linux/irq.h>  
#include <asm/uaccess.h>  
#include <asm/irq.h>  
#include <asm/io.h>  
// #include <mach/regs-gpio.h>  
// #include <mach/hardware.h>  
  
/* 1. 确定主设备号 */  
static int major;  
  
static int hello_open(struct inode *inode, struct file *file)  
{  
    printk("hello_open\n");  
    return 0;  
}  
  
static int hello2_open(struct inode *inode, struct file *file)  
{  
    printk("hello2_open\n");  
    return 0;  
}  
  
  
/* 2. 构造file_operations */  
static struct file_operations hello_fops = {  
    .owner = THIS_MODULE,  
    .open  = hello_open,  
};  
  
static struct file_operations hello2_fops = {  
    .owner = THIS_MODULE,  
    .open  = hello2_open,  
};  
  
  
#define HELLO_CNT   2  
  
static struct cdev hello_cdev;  
static struct cdev hello2_cdev;  
static struct class *cls;  
  
static int hello_init(void)  
{  
    dev_t devid;  
      
    /* 3. 告诉内核 */  
	if (major) {  
	  devid = MKDEV(major, 0);    //返回dev_t类型的设备编号  
	  /* (major,0~1) 对应 hello_fops, (major, 2~255)都不对应hello_fops */  
        register_chrdev_region(devid, HELLO_CNT, "hello");  
    } else {  
/* (major,0~1) 对应 hello_fops, (major, 2~255)都不对应hello_fops */  
        alloc_chrdev_region(&devid, 0, HELLO_CNT, "hello"); 
        major = MAJOR(devid);   //获取主设备号                    
    }  
      //静态初始化一个cdev结构体变量，内核中每个字符设备都对应一个 cdev 结构的变量  
    cdev_init(&hello_cdev, &hello_fops); 
    cdev_add(&hello_cdev, devid, HELLO_CNT); //把cdev添加到系统中去  
  
    devid = MKDEV(major, 2);  
    register_chrdev_region(devid, 1, "hello2");  
    cdev_init(&hello2_cdev, &hello2_fops);  
    cdev_add(&hello2_cdev, devid, 1);  
      
    cls = class_create(THIS_MODULE, "hello");  
    device_create(cls, NULL, MKDEV(major, 0), NULL, "hello0"); /* /dev/hello0 */  
    device_create(cls, NULL, MKDEV(major, 1), NULL, "hello1"); /* /dev/hello1 */  
    device_create(cls, NULL, MKDEV(major, 2), NULL, "hello2"); /* /dev/hello2 */  
    device_create(cls, NULL, MKDEV(major, 3), NULL, "hello3"); /* /dev/hello3 */  
      
      
    return 0;  
}  
  
static void hello_exit(void)  
{  
    device_destroy(cls, MKDEV(major, 0));  
    device_destroy(cls, MKDEV(major, 1));  
    device_destroy(cls, MKDEV(major, 2));  
    device_destroy(cls, MKDEV(major, 3));  
    class_destroy(cls);  
  
    cdev_del(&hello_cdev);  //从系统中删除cdev  
    unregister_chrdev_region(MKDEV(major, 0), HELLO_CNT);  
  
    cdev_del(&hello2_cdev);  
    unregister_chrdev_region(MKDEV(major, 2), 1);  
}  
  
module_init(hello_init);  
module_exit(hello_exit);  
MODULE_LICENSE("GPL");  
